#pragma  once
#include "Part.h"
#include <map>
#include "Common/CharacterDefine.h"
#include "Common/AccountDefine.h"
#include "Creature.h"
#include "Common/Event/Event.h"
#include "MissionPart.h"

class Player : public Creature
{
	typedef bool(Player::*pFunc)(uint32_t);
	typedef bool(Player::*pMsgFunc)(const char*, uint32_t);
	typedef std::unordered_map<int32_t, pFunc> CalculateFunc;
	typedef std::unordered_map<int32_t, pMsgFunc> MsgFunc;
	typedef std::vector<CharIDType> VECCID;			//cid数组
	enum enTimeID
	{
		enTime_Relive = 1,
		enTime_RevertHP =2,
		enTime_LeiGua   = 3,
	};
protected:
	//内部属性接口
	//高级属性换算
	bool  AdvanceAttrFormula(uint32_t PANum,int64_t nValue);
	//加法属性公式入口
	bool  AttrsFormula(uint32_t PANum);
	//最终值属性公式入口
	bool  FinalAtrrFormula();

	void  SynAttrCache(uint32_t PANum);
	void  SynAttr();
	bool  ReadBaseData(CharacterDBInfo &PlayerInfo);
	void  SetAccountInfo(CharLoginInfo* pLoginInfo);
	//这里面没有同步到客户端属性的消息，如果要同步，请在外面自己同步
	bool  LevAttrs(bool levUp = true);
	void  InitLevAttrs();

	//属性计算最终公式 
	void FinallyCalcChangeAttr();

	//////////////////////////////////////////////////////////////////////////

	//外部消息处理接口
	MsgFunc m_mapMsgFunc; //函数注册表
	bool  C2AttrPoint(const char* data, uint32_t nlen); //分配点加一级属性
	bool  C2AttrClearPoint(const char* data, uint32_t nlen); //洗属性
	bool  C2AutoAttrPoint(const char* data, uint32_t nlen); //自动分配属性点
	bool  C2RelivePlayer(const char* data, uint32_t nlen);  //玩家静态地图复活
	bool C2SaveGuidelines(const char* data, uint32_t nlen); //保存新手指引
	bool C2SavePlot(const char* data, uint32_t nlen);  //保存过场动画
	bool C2UseMonster(const char* data, uint32_t nlen); //使用怪物
	bool StartTalkToNpc(const char* data, uint32_t nlen); //开始同NPC讲话
	bool StopTalkToNpc(const char* data, uint32_t nlen); //开始同NPC讲话
	bool FetchMissionPrestige(const char* data, uint32_t nlen);//领取任务声望奖励
	//客户端通知加载完成,主要为了解决人物传送中途有消息，和传过去客户端没加载完，即被别的玩家看到的问题
	bool C2LoadMapFinish(const char* data, uint32_t nlen);
	//////////////////////////////////////////////////////////////////////////
protected:
	Part*   m_pPart[PART_MAX];
	int32_t m_attrs[P_MAX];
	int64_t m_attrs64[P_ATTR_ULONG_END];    //64位属性
	SynAttrsToSingleClient m_attrClient;	 //个人属性同步缓存

	Point3<float> m_lastPos;               //上个地图生物坐标
	uint32_t m_lastSceneId;                //id
	uint32_t m_lastMapId;                  //上个地图模板id

	bool	m_isFightState;					//是否是战斗状态

	//时间
	uint64_t m_deadIntervalTime;   //死亡时间戳
	uint64_t m_createTime;			 //创建时间（UTC时间）
	uint64_t m_lastSaveTime; 		 //最后一次存盘的时间（UTC时间）
	uint64_t m_onlineTime;   		 //总在线游戏时间(秒)
	uint64_t m_loginTime;    		 //上一次登陆的时间（UTC时间）
	uint64_t m_logoutTime;   		 //上一次下线时间（UTC时间）
	uint64_t m_startFightStateTime;	// 变为战斗状态开始时间
	//////////////////////////////////////////////////////////////////////////

	string m_strGuidelines;				//新手指引信息
	string m_strPlot;					//过场动画
	float  m_fRadius;					//人物半径
	uint32_t m_nFightStatusTime;		//战斗状态持续时间
protected:
	std::string m_name;						// 游戏内的角色名字

	//std::string m_userid;						// 用户帐号id
	//std::string m_channelId;				// 渠道id
	//std::string m_userName;					// 渠道用户名字
	//std::string m_account;					// db channel_user_id

	uint64_t	m_token;
	uint32_t    m_zid;                      //区服id
	uint32_t    m_uid;                      //帐号id
	uint32_t    m_clientId;                 //客户端Id
	uint32_t    m_chanId;					//玩家渠道Id
	uint32_t    m_gateId;                   //玩家网关Id

	ISession *m_pPlayerSession;				// 客户端连接会话

	AccountGameState	m_accountState;		// 此账号在游戏中的状态
	LOGOUT_FLAG         m_logoutFlag;		// 玩家退出游戏的原因（正常退出，被提出等）
	bool				m_leaveGameSave;	// 是否离开游戏存盘

	HostNode    m_hostNode;
private:
	//需要同步到中心服的属性处理,目前主要针对组队需要实时更新位置和血量信息
	bool m_isLastMove;	//上次是否在移动
	uint32_t m_lastHp;		//上一次的生命值
	CharacterArenaData m_arenaData; //竞技场数据
	string m_unionName;	//工会名字
	SET_UINT32 m_setMissionPrestige;//已领取的任务声望奖励
	VEC_STRING m_buChanInfo;	//停服维护版本更新补偿领取记录信息
	bool		m_bIsNeedCalcFight;  //是否需要计算战斗力

	VEC_UINT32  m_vChangeAdvanceAttr; //有非基础属性改变，需要重新计算相关的基础属性
	VEC_UINT32  m_vChangeBaseAttr;	  //一次改变的所有基本属性

	int64_t		m_iLeiGuaAllTime;		//内挂持续总时长 单位秒
	uint64_t    m_i64StartUseLeiGuaItem;	//开始使用内挂道具时间 取到秒

	PlayerActiveAnswerData  m_activeData;	//玩家世界答题活动数据
	PlayerActiveAnswerData  m_activeDailyData;	//玩家每日答题活动数据
	VECCID      m_createMyselfMonsterCid;			//创建的专属怪物CID

	CharacterDBGuideDupInfo m_guideDup;
public:
public:
	Player();
	virtual ~Player();

	bool Init(CharacterDBInfo &PlayerInfo, CharLoginInfo* pLoginfo);
	virtual bool UnInit();
	virtual void Update(uint64_t tick);

	//外部属性接口
	const std::string& GetName() const { return m_name; };
	uint32_t GetZid() const { return m_zid; }

	virtual void OnExecute(uint16_t nEventID, uint64_t nSrcID, uint8_t bySrcType, void *pContext, int32_t nLen);

	virtual void GetVisibleDataToClient(CreaturesCreateData& CvData);
	virtual void SynAttrToClient();
	bool SynLoginInfo(); //角色数据同步客户端

	virtual bool CheckAttrValue(uint32_t CANum, uint32_t attrValue);
	virtual bool AddAttr(uint32_t CANum, int64_t attrValue, bool syn, uint64_t relationCid = 0);
	virtual bool AddAttrCache(uint32_t CANum, int64_t attrValue, uint64_t relationCid = 0);
	virtual void SetAttr(uint32_t CANum, int64_t attrValue, bool syn = false);
	virtual void SetAttrCache(uint32_t CANum, int64_t attrValue);
	virtual int64_t GetAttr(uint32_t CANum) ;
	virtual int64_t GetPAttrValue(uint32_t attrPANum);
	virtual uint32_t GetAttrNum(uint32_t CommonAttrNum);
	virtual Part* GetPart(uint32_t partType);
	virtual uint32_t GetUid() { return m_uid; }
	uint32_t GetChannId(){ return m_chanId; }

	virtual uint32_t GetClientId(){ return m_clientId; }
	virtual void GetGateClientId(uint32_t& gateId, uint32_t& clientId){ gateId = m_gateId; clientId = m_clientId; }
	void	SetClientID(uint32_t clientId){ m_clientId = clientId; };
	void   SetSpeed(float f, bool isSync = false);
	virtual AccountGameState GetAccountState();
	//是否是允许负数
	bool   IsCanNegativeAttr(uint32_t attrPANum);
	//是否是需要计算战斗力属性
	bool   IsNeedCalcFightAttr(uint32_t attrPANum);
	//是否是战斗属性，战斗属性在调属性修改时，他修改的相关所有属性都不用计算战斗力
	bool   IsFightAttr(uint32_t attrPNum);
	//视野裁剪接口
	virtual bool ViewFliter(Creature* pCreature, float dict);
	virtual void OnTimer(uint32_t nTimerID);
	//virtual void UpdateSeeLst();

	bool  AddAttrPA(uint32_t PANum, int64_t attrValue, bool syn, uint64_t relationCid = 0);
	bool  AddAttrPACache(uint32_t PANum, int64_t attrValue, uint64_t relationCid = 0);
	void  SetAttrPA(uint32_t PANum, int64_t attrValue, bool syn = false, bool isCalc = true);
	void  SetAttrPACache(uint32_t PANum, int64_t attrValue,bool isCalc=true);
	void  SetLastSceneInfo();

	virtual void OnDead(CharIDType killerCid);
	virtual void OnRevive(CharIDType saverCid);
	void OnRevive(CharIDType saverCid,int64_t curHp,int64_t curMp);

	bool ForceReturnLastPlace(); //强制回到上个地图位置
	bool EnterScene(uint32_t sceneId, Point3<float>& enterPos, STransParam &transParam);
	bool LeaveScene();
	void SetAccountState(AccountGameState state);
	
	//获取上一次的地图ID
	uint32_t GetLastMapId() { return m_lastMapId; };
	//获取上一次的场景ID
	uint32_t GetLastSceneId() { return m_lastSceneId; }
	//获取上一次的坐标
	Point3<float> GetLastPos() { return m_lastPos; }
	//获取外观
	//void GetFacade(uint32_t &clothesId, uint32_t &weaponId, uint32_t &wingId);
	void GetFacade(CharFacadeProto *facade);

	//scenceId:目标场景ID（唯一ID，静态地图场景ID和地图ID相同），dstPos：目标场景坐标，mapId：地图ID,transParam:传送参数
	virtual bool TransScene(uint32_t scenceId, Point3<float>& dstPos, uint32_t mapId, STransParam &transParam);
	virtual bool MoveTo(Point3<float> dstPos);					//移动
	virtual void StopMove();									//停止当前移动,广播告诉其他人
	//瞬间移动
	virtual bool Teleporting(Point3<float> dstPos);
	//被击退
	virtual bool BeatBack(Point3<float> dstPos);


	//获取怪物模型半径, 长度单位m
	virtual float GetModelRadius(){ return m_fRadius; };

	//激活内挂道具
	void ActiveLeiGuaItem(int32_t activeTime);

	//同步内挂有效时间到客户端,单位秒
	void SyncLeiGuaLeftTimeToClient(uint64_t leftTime);

	//是否在内挂时间内
	bool IsLeiGuaActiveTime();
	//给生物加状态包
	//pTarget为空，则是给自己加状态包
	//virtual bool AddStateBag(uint32_t skillid, uint32_t lev, ProtoBuf::BuffBagDetailInfo* pClientStatebag, Creature* pTarget = nullptr);
	//////////////////////////////////////////////////////////////////////////

	//外部消息接收接口
	bool OnMsgHandle(uint32_t cmd, const char * data, uint32_t len);

	//登入游戏
	bool LoginInGame(CharLoginInfo& loginInfo, bool change = false);
	//切换逻辑节点成功的处理
	void OnChangeLogic();
	//切逻辑节点同步基础属性
	void OnChangeLogicSynAttr();
	//同步中心服玩家相关的属性
	void OnCharCenterData(CharLoginSyncCenterData &protoSync);

	//同步互客户端玩家非buff状态
	void UpdateStateToClient();

	//加经验值,所以升级接口都从这里走
	//param1 本次加的经验总值
	//param2 本次加的基础经验
	//param3 本次加的其它经验 暂时是组队+亲密度
	void AddExp(uint32_t expNum,uint32_t baseExp=0,uint32_t otherExp=0);

	//设置队伍属性
	void SetTeamAttr(uint32_t teamId,uint32_t isLeader,bool bsync = false);
	//同步属性到中心服 属性ID为 C_ 开头的属性
	void SyncToCenter(int32_t C_attrId);
	//更新工会属性
	void SetUnionAttr(uint32_t unionId, const string &strName,int32_t duty,int32_t level,int32_t icon,int32_t contri,int32_t officeLev,int32_t vaultLev,uint32_t homeScene,bool syn=false);
	//获取工会名字
	const string &UnionName();
	//设置房间属性
	void SetRoomAttr(uint32_t roomId, int32_t isOwner);

	//完成新手引导副本步骤
	void FinishGuideDupStep(uint32_t step);
	//完成新手引导副本
	void FinshAllGuideStep();
	//是否已经完成新手引导副本
	bool IsFinishGuideDup();

	//登陆同步中心服的角色数据
	bool CenterCharacterPack(CenterCharacterInfo* centerPackage);

	//最近复活点复活
	bool OnNearBornRevive();
	//获取复活点坐标和地图
	bool OnGetNearBornReliveInfo(uint32_t &nMapId,uint32_t &sceneId, Point3<float> & pos);

	//获取玩家升级和加点所加的6个基础属性值（力量,智力,敏捷,体质,耐力,精准）
	//数组 中按顺序存的各个属性的值 
	void GetLevelAddPointAttr(int64_t * pAttr,int num=6);

	//同步获取经验到客户端
	void SyncExpToClient(uint32_t baseExp,uint32_t otherExp);

	//收到中心服的排名信息
	void ReqCenterRankingListIndex(uint32_t type,uint32_t index);

	//获取玩家活动信息
	PlayerActiveAnswerData & GetPlayerAnswerData();
	//设置玩家活动信息
	void SetPlayerAnswerData(PlayerActiveAnswerData & data);
	//清除玩家身上的答题活动
	bool ClearAnswerActiveData();

	//获取玩家每日答题活动
	PlayerActiveAnswerData & GetPlayerDailyAnswerData();
	//设置玩家每日答题活动信息
	void SetPlayerDailyAnswerData(PlayerActiveAnswerData & data);
	//清除玩家身上的每日答题活动
	bool ClearDailyAnswerActiveData();

	//添加专属怪物的cid
	void AddOnwerMyselfMonsterCid(CharIDType cid);
	//判断是否是自己专属怪
	bool IsOnlyOwnerMonster(CharIDType cid);
//------------------------------------------------------------------------------------------------------

	/////////////////////////////PVP 相关 //////////////////////////////////
	bool	 IsFriendSide(Creature* pCreature);
	uint32_t	 GetCampId();
	bool	 IsSameCamp(Player* player);
	bool	 IsTeammates(Player* player); //是否是队友，暂时未false，包过玩家，玩家携带的宠物或召唤物
	bool	 IsSameUnion(Player* player); //是否是一个公会的,包过玩家，玩家携带的宠物或召唤物
	bool	 IsNewPlayer();
	void	 AddPkKillingValue(uint32_t addon);
	void	 SubPkKillingValue(uint32_t addon);
	void   SendPvpKillingValue();
	uint32_t GetPkKillingValue();
	uint32_t GetPkMode();
	void	 SetPkMode(uint32_t pkMode);
	void	 AddRedPlayer(Player* player);
	bool	 IsRedPlayer(Player* player);
	bool	 IsWanted(); //是否被通缉
	bool	 IsFightState(); //是否战斗状态
	void	 ClearFightState(); // 清空战斗状态
	//////////////////////////////////////////////////////////////////////////


	//////////////////////////////每日每周刷新接口///////////////////////////////
	bool DailyUpdate(uint64_t unixSec);
	bool WeekUpdate(uint64_t unixSec);
	//////////////////////////////每日零点 每周一零点 刷新接口///////////////////////////////
	bool DailyZeroUpdate(uint64_t unixSec);
	bool WeekZeroUpdate(uint64_t unixSec);
	/////////////////////////////////////////////////////////////////////////

	//////////////////////////////活动相关//////////////////////////////////
	//判断玩家是否拥有杀戮之子状态
	bool InSonOfKillingStatus();
	//判断玩家是否杀戮之子死亡免惩罚
	bool RemitSonPKPunish();
	//判断玩家是否拥有混沌之龙状态
	bool InWorldBossStatus();

	//判断是否在流放之地地图
	bool IsInJail();

	//发送T除玩家信息到中心服
	bool SendKickPlayerToCenter();
public:
	//判断生物身上是否有buff状态包
	virtual bool HasBuffStateBag(uint32_t stateBagId);
	virtual void BuffEffect_ReduceDamage(Creature* pAttack, uint32_t skillId, int32_t &damage);
	virtual void BuffEffect_AddExtraDamage(Creature* pBeAttacked, uint32_t skillId, int32_t &damage);
	virtual void BuffEffect_CleanupAllFadeOutEffects(BuffInfoEndType endType);
public:
	virtual bool CanTrans(ERetCode &ret, uint32_t dstSceneId, uint32_t dstMapId);

	CharIDType GetId();
	void SetAccount(string account);

	void SetLogoutFlag(LOGOUT_FLAG flag);

	HostNode* GetHostNode();
	uint64_t GetLastSaveTime();
	uint64_t GetLogoutTime();
	uint64_t GetOnlineSec();
	uint64_t GetLoginTime();

	bool Logout(LOGOUT_TYPE type = LOGOUT_TYPE_NONE);
	bool ChangeLogic();

	bool TriggerSave(bool direct = false);
	bool GetSaveDBData(CharacterDBInfo& charInfo);

	void GetSellItems(PlayerSellBackItem& sellItem);
	void SetSellItems(const PlayerSellBackItem& sellItem);

	// 分帧任务处理函数
	bool DoTask(TaskNodeId type, void* data, uint32_t size);

	//校验坐标，为true表示一致，false表示不一致  distance  表示允许的误差距离
	bool CheckPos(Point3<float> &tmpPos,uint32_t distance=3);

	//计算战力，总战斗力=属性战斗力+人物技能战斗力+精灵技能战斗力+主宝石战斗力
	uint32_t CalcPlayerFightPower(bool sync=false);
	//计算人物属性所加战力,不传则计算人物的
	//传入则必需转成人物基属属性ID，传入必需将你的属性赋给玩家属性下标值
	//比如pAttr[P_CRIT_RATE] = m_attrs[P_EQUIP_CRIT_RATE]
	float CalcAttrFightPower(int32_t * pAttr = NULL, uint32_t creatureKind = CREATURE_PLAYER);
private:
	bool _DoSave(bool direct = false);
	bool _Serialize(CharacterDBInfo& charInfo);
	bool _SaveCharacterBaseData(CharacterDBInfo& charInfo);		// db m_base_data
	bool _SaveCharacterExtraData(CharacterDBInfo& charInfo);
	bool _SaveCharacterArenaData(CharacterDBInfo& charInfo);
	void _SetCharacterDetailAttr(CharacterDBAttrDetailInfo *pattr);

	////////////////////////////////////////////////////////////////////////////////
	// lua class
	// lua 注册函数不支持有64位和枚举类型的的函数注册，需要重新包装为支持的类型
	// 返回值为bool类型的函数一律重新封装为返回值为int类型的lua函数
public:
	static bool RegistLuaClass(lua_State* state);
	string LuaGetChannelId();
	uint32_t LuaGetUId();
	string LuaGetChannelUserName();
	int32_t LuaGetAttr(uint32_t CANum);

public:
	virtual void  LogBase(LogTid logid, JsonObject &obj);

	//玩家登陆流水日志
	void  LoginLog();
	//玩家升级流水日志
	void  LevUpLog();
	//玩家离线流水日志
	void  LoginOutLog();
	//玩家货币流水日志
	void  CurrencyLog(LogTid logid, uint32_t currencyid, uint32_t num, uint32_t source, const char* currencyName, uint64_t preValue, uint64_t newValue);
	//玩家商城流水日志
	void  MallLog(MallLogInfo& mall);
	//玩家精炼水流日志
	void  RefineLog(uint32_t equipid, uint32_t preLvl, uint32_t newLvl, const string& equipName, const string& stoneName, uint32_t count, uint32_t gold, uint64_t preValue, uint64_t newValue, bool success);
	//玩家宝石镶嵌水流日志
	void  InlayLog(uint32_t equipid, const string& equipName, const string& stoneName);
	//玩家符文镶嵌水流日志
	void  RuneLog(uint32_t equipid, const string& equipName, const string& runeName);
	//玩家公会精修水流日志
	void  UnionUpgradeLog(uint32_t lvl, uint32_t contri, uint64_t preContri, uint64_t newContri, uint32_t gold, uint64_t preGold, uint64_t newGold);
	//玩家神格流水日志
	void GodLog(uint32_t clId, uint32_t count, uint32_t gold, const string& godName, uint32_t godLev);
	//玩家物品流水日志
	void ItemLog(LogTid logTid, JsonObject &obj, uint32_t source);
	//玩家接取任务
	void MissionAccpectLog(uint32_t missionid, string& missionName, uint32_t typeId);
	//玩家完成任务
	void MissionCompleteLog(uint32_t missionid, string& missionName, uint32_t typeId, uint32_t completeSec);
	//玩家任务失败
	void MissionFailLog(uint32_t missionid, string& missionName, uint32_t typeId, const char* reason);
	//充值日志
	void PayLog(const string& productId, const string& payOrder, uint32_t money, uint32_t diamond, uint32_t firstDiamond);

public://竞技场相关
	void AddArenaChallengeTimes();
	uint32_t GetArenaChallengeTimes();
	void SetArenaBestRankId(uint32_t histroyId);
	uint32_t GetArenaBestRankId();

public://登录补偿
	inline VEC_STRING& GetChangeVersion() { return m_buChanInfo; }
};
